<?php

namespace core\lib;

class LibCode
{
    /**
     * 类型 验证码
     * 纯数字
     * @var int
     */
    const NUMERIC = 1;

    const ALPHABET_LOWER = 2;

    const ALPHABET_UPPER = 3;

    const MIX = 4;

    /**
     * @var int 生成密码
     */
    const PASSWORD = 5;

    const DEFAULT_LENGTH = 6;

    /**
     * code 类型
     * @var int
     */
    public $codeType = 0;

    /**
     * code 长度
     * @var int
     */
    public $codeLength = 0;

    public function __construct($type = self::NUMERIC, $length = self::DEFAULT_LENGTH)
    {
        $this->codeType = $type;
        $this->length = $length;
    }

    public function getCode()
    {
        $str = $this->getStrByType();
        $rs = '';
        for ($i = 0; $i < $this->length; $i++) {
            $rs .= substr($str, rand(0, strlen($str) - 1), 1);
        }
        return $rs;
    }

    public function numStr()
    {
        return '0123456789';
    }

    public function alphabetStr()
    {
        return 'abcdefghijklmnopqrstuvwxyz';
    }

    public function specialSymbol()
    {
        return '!@#$%^*()';
    }

    /**
     * 根据类型返回对应的字符串
     */
    public function getStrByType()
    {
        switch ($this->codeType) {
            case self::NUMERIC:
                return $this->numStr();
                break;
            case self::ALPHABET_LOWER:
                return $this->alphabetStr();
                break;
            case self::ALPHABET_UPPER:
                return strtoupper($this->alphabetStr());
                break;
            case self::MIX:
                return $this->numStr() .
                    $this->alphabetStr() .
                    strtoupper($this->alphabetStr());
                break;
            case self::PASSWORD:
                return $this->getPasswordStr();
                break;
        }
        throw new \Exception('code type error', 500);
    }

    public function getPasswordStr()
    {
        // 特殊符号权重需要占多一点
        return $this->numStr() .
            $this->specialSymbol().
            $this->alphabetStr() .
            $this->specialSymbol().
            strtoupper($this->alphabetStr());
    }

    public static function get($codeType = self::NUMERIC, $length = self::DEFAULT_LENGTH)
    {
        return (new self($codeType, $length))->getCode();
    }
}
